﻿/*  
	========================================================================
	 awzBoxes Library
	
	 Homepage: http://www.awzhome.de/
	========================================================================
	
	This Source Code Form is subject to the terms of the Mozilla Public
	License, v. 2.0. If a copy of the MPL was not distributed with this
	file, You can obtain one at http://mozilla.org/MPL/2.0/.
   
	The Original Code is code of awzBoxes Library.

	The Initial Developer of the Original Code is Andreas Weizel.
	Portions created by the Initial Developer are
	Copyright (C) 2011-2012 Andreas Weizel. All Rights Reserved.
	
	Contributor(s): (none)
	
	========================================================================
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Media;

namespace AWZhome.awzBoxes.Tools
{
	/// <summary>
	/// Helper class with additional methods for traversing the visual tree of controls.
	/// </summary>
	public class ControlFinder
	{
		/// <summary>
		/// Gets a control at a specific location.
		/// Walks up the visual tree to find a container control.
		/// </summary>
		/// <typeparam name="T">Type of searched control.</typeparam>
		/// <param name="reference">Reference control for location coordinates.</param>
		/// <param name="location">Location to search the control at.</param>
		/// <returns>The found control or <c>null</c>, if no control matched the requested type.</returns>
		public static T GetControlAtLocation<T>(Visual reference, Point location)
			where T : FrameworkElement
		{
			T foundItem = default(T);
			HitTestResult hitTestResults = VisualTreeHelper.HitTest(reference, location);
			if (hitTestResults != null)
			{
				foundItem = hitTestResults.VisualHit as T;
				if (hitTestResults.VisualHit is FrameworkElement)
				{
					foundItem = FindAncestor<T>(hitTestResults.VisualHit);
				}
			}

			return foundItem;
		}

		/// <summary>
		/// Walks up the visual tree to find a specific parent control.
		/// </summary>
		/// <typeparam name="T">Type of searched control</typeparam>
		/// <param name="current">Control from that the search should be started.</param>
		/// <returns>The found control or <c>null</c>, if no control matched the requested type.</returns>
		public static T FindAncestor<T>(DependencyObject current)
			where T : Visual
		{
			do
			{
				if (current is T)
				{
					return (T) current;
				}
				if (current is Visual)
				{
					current = VisualTreeHelper.GetParent(current);
				}
				else
				{
					// Current element is not a Visual any more, 
					current = null;
				}
			}
			while (current != null);
			return null;
		}
	}
}
